#include "arc.h"

#include "expression.h"
#include "place.h"
#include "transition.h"
#include "wfnet.h"

#include <edge.h>
#include <typefactory.h>

using namespace wfnet;

Arc::~Arc()
{

}

nid Arc::getId() const
{
    return m_id;
}

IExpression* Arc::getExpression() const
{
    return m_expression;
}

BasicTime Arc::getDelay() const
{
    return m_delay;
}

void Arc::setExpression(IExpression *expression)
{
    m_expression = dynamic_cast<Expression* >(expression);
}

void Arc::setDelay(const BasicTime &time)
{
    m_delay = time;
}

Place* Arc::getPlace() const
{
    return m_place;
}

Transition* Arc::getTransition() const
{
    return m_transition;
}

Arc::ConnectionType Arc::getConnectionType() const
{
    return m_connectionType;
}

void Arc::registerEdge(Edge* edge)
{
    m_edge = edge;
}

const Edge* const Arc::edge() const
{
    return m_edge;
}

IMultiset* Arc::eval(BasicTime globalClock) const
{
    const WfNet* net = qobject_cast<const WfNet* >(parent());

    Q_ASSERT(net != 0);

    IMultiset* imt = 0;

    if (m_expression != 0)
    {
        Type* type = m_expression->eval();

        IMultiset* mt = dynamic_cast<IMultiset* >(type);
        if (mt != 0)
        {
            imt = mt;
        }
        else
        {
            ColorSet* color = 0;

            const QSet<ColorSetName> regColorSets =
                net->registeredColorSets();

            foreach (const ColorSetName& name, regColorSets)
            {
                const ColorSet* _color = dynamic_cast<const ColorSet* >(
                    TypeFactory::getInstance()->getTypeInstance(name));

                Q_ASSERT(_color != 0);

                if (_color->matches(type->name()) && _color->isTimed() ==
                    m_place->getColorSet()->isTimed())
                {
                    color = new ColorSet(*_color);
                    break;
                }
            }

            ValueType* valType = dynamic_cast<ValueType* >(type);

            color->setValue(valType->getValue());

            delete type; // no longer needed;

            if (color->isTimed())
            {
                TimedMultiset* tmt = dynamic_cast<TimedMultiset* >(
                    TypeFactory::getInstance()->getTypeInstance(
                        TimedMultiset::constructName(color->name()))->copy());

                Q_ASSERT(tmt != 0);

                globalClock.add(m_delay.getTime());
                tmt->insert(*color, globalClock);

                imt = tmt;
            }
            else
            {
                Multiset* mt = dynamic_cast<Multiset* >(
                    TypeFactory::getInstance()->getTypeInstance(
                        Multiset::constructName(color->name()))->copy());

                Q_ASSERT(mt != 0);

                mt->insert(*color);

                imt = mt;
            }

            delete color; // no longer needed
        }
    }

    return imt;
}

Arc::Arc(WfNet* parent, nid id, Place* place, Transition* transition,
    ConnectionType type, BasicTime delay) : QObject(parent),
    IArc(), IEdgeData(),
        m_edge(0),
        m_id(id),
        m_place(place),
        m_transition(transition),
        m_expression(0),
        m_connectionType(type),
        m_delay(delay)
{

}
